package com.dd.seckill.single.service.internal.impl;

import com.dd.seckill.single.config.cache.caffeine.CaffeineCacheConfig;
import com.dd.seckill.single.config.exception.BusinessException;
import com.dd.seckill.single.pojo.DO.SeckillGoods;
import com.dd.seckill.single.mapper.SeckillGoodsMapper;
import com.dd.seckill.single.service.cache.SeckillGoodsCacheService;
import com.dd.seckill.single.service.cache.TwoLevelCacheService;
import com.dd.seckill.single.service.internal.ISeckillGoodsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.benmanes.caffeine.cache.Cache;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 秒杀商品表 服务实现类
 * </p>
 *
 * @author liuxianmeng
 * @since 2025-09-06
 */
@Service
@RequiredArgsConstructor
public class SeckillGoodsServiceImpl extends ServiceImpl<SeckillGoodsMapper, SeckillGoods> implements ISeckillGoodsService {

    private final TwoLevelCacheService cacheService;
    private final SeckillGoodsMapper seckillGoodsMapper;
    private final SeckillGoodsCacheService seckillGoodsCacheService;

    /**
     * 查询所有秒杀商品信息
     *
     * @return List<SeckillGoods>
     */
    public List<SeckillGoods> seckillGoodsList() {
        return seckillGoodsCacheService.getSeckillGoodsList();
    }

    /**
     * 获取商品信息（带二级缓存）
     */
    public SeckillGoods getGood(String goodsId) {
        String cacheKey = "goodsId:" + goodsId;

        return cacheService.get(cacheKey, SeckillGoods.class, () -> {
            // 缓存不存在时从数据库加载
            SeckillGoods seckillGoods = seckillGoodsMapper.selectById(goodsId);
            if(seckillGoods == null){
                throw new BusinessException(500, "cacheKey(" + cacheKey + ")指向的商品不存在");
            }
            return seckillGoods;
        }, 30, TimeUnit.MINUTES);
    }

    /**
     * 更新商品信息（保证缓存一致性）
     */
    @Transactional
    public SeckillGoods updateGood(String goodsId, SeckillGoods seckillGoods) {
        // 1. 更新数据库
        seckillGoodsMapper.updateById(seckillGoods);

        // 2. 删除缓存（让下次读取时重新加载）
        String cacheKey = "goodsId:" + goodsId;
        cacheService.delete(cacheKey);
        seckillGoodsCacheService.refreshCache();

        return seckillGoods;
    }

    /**
     * 强一致性更新
     */
    @Transactional
    public SeckillGoods updateGoodWithConsistency(String goodsId, SeckillGoods seckillGoods) {
        String cacheKey = "goodsId:" + goodsId;

        // 1. 先删除所有缓存
        cacheService.delete(cacheKey);
        // 2. 更新数据库
        seckillGoodsMapper.updateById(seckillGoods);
        // 3. 立即刷新缓存（强一致性）
        cacheService.set(cacheKey, seckillGoods, 30, TimeUnit.MINUTES);

        return seckillGoods;
    }
}
